"""
文件操作工具模块。
提供文件和目录操作的工具类和函数。

推荐使用方式:
    from src.base.file_utils import FileUtils

    # 创建目录
    FileUtils.create_directory_if_not_exists("path/to/dir")

    # 保存JSON数据
    FileUtils.save_json(data, "output.json")


兼容方式:
    from src.base.file_utils import create_directory_if_not_exists, save_json

    create_directory_if_not_exists("path/to/dir")
    save_json(data, "output.json")
"""

import os
import json
import shutil
from typing import Optional, List, Any, Dict
from .registry import bera
from pathlib import Path
from .path_utils import PathUtils

class FileUtils:
    """文件操作工具类"""

    @classmethod
    def create_directory_if_not_exists(cls, directory: str) -> None:
        """
        检查目录是否存在,不存在则创建。

        Args:
            directory: 目录路径
        """
        if not directory:
            bera.logger.warning('Creating directory: params error')
            return

        if not os.path.exists(directory):
            os.makedirs(directory)
            bera.logger.info(f"Directory '{directory}' created.")
        else:
            bera.logger.info(f"Directory '{directory}' already exists.")

    @classmethod
    def get_directory_up_level(cls, path: str, level: int = 1) -> str:
        """
        获取指定路径向上level层的目录。

        Args:
            path: 起始路径
            level: 向上层数,默认1层

        Returns:
            目标目录的路径
        """
        current_dir = os.path.dirname(path)
        for _ in range(level):
            current_dir = os.path.dirname(current_dir)
        return str(current_dir)

    @classmethod
    def delete_file_if_exists(cls, file_path: str) -> None:
        """
        如果文件存在则删除。

        Args:
            file_path: 文件路径
        """
        if os.path.exists(file_path):
            os.remove(file_path)
            bera.logger.info(f"File '{file_path}' deleted.")
        else:
            bera.logger.info(f"File '{file_path}' does not exist.")

    @classmethod
    def recreate_directory(cls, directory: str) -> None:
        """
        重新创建目录,如果存在则先删除。

        Args:
            directory: 目录路径
        """
        if os.path.exists(directory):
            shutil.rmtree(directory)
            bera.logger.info(f"Directory '{directory}' deleted.")
        os.makedirs(directory)
        bera.logger.info(f"Directory '{directory}' created.")

    @classmethod
    def copy_directory(cls, src_dir: str, dst_dir: str, log_file=None, delete_dst: bool = True) -> None:
        """
        复制目录。

        Args:
            src_dir: 源目录
            dst_dir: 目标目录
            log_file: 日志文件对象
            delete_dst: 是否删除已存在的目标目录
        """
        if os.path.exists(src_dir):
            if os.path.exists(dst_dir) and delete_dst:
                shutil.rmtree(dst_dir)
            shutil.copytree(src_dir, dst_dir)
            bera.logger.info(f"Copied {src_dir} to {dst_dir}")
            if log_file:
                log_file.write(f"Copied {src_dir} to {dst_dir}\n")
        else:
            bera.logger.warning(f"Directory {src_dir} does not exist")
            if log_file:
                log_file.write(f"Directory {src_dir} does not exist\n")

    @classmethod
    def copytree_force(cls, src: str, dst: str) -> None:
        """
        强制复制目录或文件。

        Args:
            src: 源路径
            dst: 目标路径
        """
        if not os.path.exists(src):
            return

        if os.path.exists(dst):
            if os.path.isdir(dst):
                shutil.rmtree(dst)
            else:
                os.remove(dst)

        if os.path.isdir(src):
            cls.copy_directory(src, dst, None)
        else:
            shutil.copy(src, dst)

    @classmethod
    def safe_move(cls, src: str, dst: str) -> None:
        """
        安全地移动文件。

        Args:
            src: 源路径
            dst: 目标路径
        """
        if not os.path.exists(src):
            bera.logger.warning(f"Source file '{src}' does not exist")
            return

        shutil.move(src, dst)

    @classmethod
    def save_file_with_log(cls, file_path: str, content: str, file_type: str = "文件", ensure_dir: bool = True) -> None:
        """
        统一的文件生成日志处理。

        Args:
            file_path: 文件路径
            content: 文件内容
            file_type: 文件类型描述，用于日志显示
            ensure_dir: 是否确保目录存在
        """
        if ensure_dir:
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        bera.logger.debug(f"{file_type}已保存到: {file_path}")

    @classmethod
    def save_json(cls, file_path: str, data: Dict[str, Any], file_type: str = "JSON文件", ensure_dir: bool = True, indent: int = 2) -> None:
        """
        保存JSON数据到文件。

        Args:
            file_path: 文件路径
            data: 要保存的数据
            file_type: 文件类型描述，用于日志显示
            ensure_dir: 是否确保目录存在
            indent: JSON缩进空格数
        """
        content = json.dumps(data, ensure_ascii=False, indent=indent)
        if ensure_dir:
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        bera.logger.debug(f"{file_type}已保存到: {file_path}")

    @classmethod
    def save_text(cls, content: str, file_path: str, ensure_dir: bool = True, file_type: str = "文本文件") -> None:
        """
        保存文本内容到文件。

        Args:
            content: 要保存的文本内容
            file_path: 输出文件路径
            ensure_dir: 是否确保目录存在
            file_type: 文件类型描述，用于日志显示

        Raises:
            IOError: 保存文件失败
        """
        if ensure_dir:
            os.makedirs(os.path.dirname(file_path), exist_ok=True)
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        bera.logger.info(f"{file_type}已保存到: {file_path}")

    @classmethod
    def read_json(cls, file_path: str) -> Dict[str, Any]:
        """
        读取JSON文件。

        Args:
            file_path: JSON文件路径

        Returns:
            Dict[str, Any]: JSON数据

        Raises:
            FileNotFoundError: 文件不存在
            json.JSONDecodeError: JSON格式错误
        """
        with open(file_path, 'r', encoding='utf-8') as f:
            return json.load(f)

    @staticmethod
    def copy_with_log(source: Path, target: Path, desc: Optional[str] = None, verbose: bool = False) -> None:
        """拷贝文件并输出统一格式的日志

        Args:
            source: 源文件路径
            target: 目标文件路径
            desc: 文件描述（不再使用）
            verbose: 是否显示日志
        """
        shutil.copy2(source, target)
        if verbose:
            source_path = PathUtils.simplify_path(source)
            target_path = PathUtils.simplify_path(target)
            bera.logger.info(f"拷贝文件 {source_path} -> {target_path}")

    @classmethod
    def copy_file(cls, source: str, target: str) -> None:
        """复制文件

        Args:
            source: 源文件路径
            target: 目标文件路径

        Raises:
            FileNotFoundError: 源文件不存在
            IOError: 复制文件失败
        """
        # 检查源文件是否存在
        if not os.path.exists(source):
            raise FileNotFoundError(f"源文件不存在: {source}")

        # 确保目标目录存在
        os.makedirs(os.path.dirname(target), exist_ok=True)

        # 复制文件
        shutil.copy2(source, target)
        bera.logger.debug(f"复制文件 {source} -> {target}")


# 为了保持向后兼容性，保留原有的函数调用方式
create_directory_if_not_exists = FileUtils.create_directory_if_not_exists
get_directory_up_level = FileUtils.get_directory_up_level
delete_file_if_exists = FileUtils.delete_file_if_exists
recreate_directory = FileUtils.recreate_directory
copy_directory = FileUtils.copy_directory
copytree_force = FileUtils.copytree_force
safe_move = FileUtils.safe_move
save_json = FileUtils.save_json
save_text = FileUtils.save_text
copy_file = FileUtils.copy_file